<template>
  <div class="winnie">
    <div class="header">
      <span class="title">系统</span>
      <span class="btn" @click="toggleAdvanceSetting">高级设置</span>
    </div>
    <div class="configuration form">
      <a-form-item label="检索时间段">
        <a-range-picker v-model="configuration.rangeTime"></a-range-picker>
      </a-form-item>

      <a-collapse v-model="option.advanceActiveKey">
        <a-collapse-panel header="高级设置" key="advanceSetting" :showArrow="false">
          <a-form-item label="提交时间的列数">
            <a-input v-model="configuration.columnOfTime" @change="saveConfigurationData"/>
          </a-form-item>

          <a-form-item label="时间格式">
            <a-input v-model="configuration.formatOfRangeTime" @change="saveConfigurationData"/>
          </a-form-item>

          <a-form-item label="总分的列数">
            <a-input v-model="configuration.columnOfTotalScore" @change="saveConfigurationData"/>
          </a-form-item>

          <a-form-item label="总分的过滤数值">
            <a-input v-model="configuration.filterValueOfTotalScore" @change="saveConfigurationData"/>
          </a-form-item>

          <a-form-item label="指定读取的工作表">
            <a-input v-model="configuration.sheetIndex" @change="saveConfigurationData"/>
          </a-form-item>

          <a-form-item label="重复数据过滤的列表">
            <a-input v-model="configuration.replicateFilterIndex" @change="saveConfigurationData"/>
          </a-form-item>

          <a-form-item label="需提取数据的列数">
            <a-checkbox-group v-model="configuration.columnsOfData" @change="saveConfigurationData">
              <a-checkbox v-for="item in option.totalColumnsOfFile" :key="item - 1" :value="item">{{ item }}</a-checkbox>
            </a-checkbox-group>
          </a-form-item>
        </a-collapse-panel>
      </a-collapse>

      <a-upload-dragger name="file" :multiple="false" :fileList="fileList" :remove="handleRemove" :beforeUpload="beforeUpload">
        <p class="ant-upload-drag-icon">
          <a-icon type="inbox"/>
        </p>
        <p class="ant-upload-text">点击或者拖动文件至此</p>
        <p class="ant-upload-hint">可一次选择多个文件批量分析处理</p>
      </a-upload-dragger>
    </div>

    <div class="confirm">
      <a-button type="primary" @click="statisticsDataAction">确定执行分析</a-button>
    </div>

    <div class="result">
      <a-card
        v-for="(dataItem, index) in analyseData"
        :key="index"
        :title="dataItem.fileName"
        style="width:100%; margin-top: 24px;"
        :tabList="getTabList(dataItem)"
        :active-tab-key="dataItem.selectedTabKey"
        @tabChange="key => dataItem.selectedTabKey = key"
      >
        <a href="javascript:void(0)" slot="extra" @click="exportFilterData(dataItem)">导出及格数据</a>
        <div v-if="dataItem.selectedTabKey === 'dashboard'">
          <div class="item">
            <div class="title">统计数据总数:</div>
            <div class="content">{{ dataItem.sourceDataTotalCount }}</div>
          </div>
          <div class="item">
            <div class="title">及格数据总数:</div>
            <div class="content">{{ dataItem.filterDataTotalCount }}</div>
          </div>
        </div>
        <div class="" v-if="dataItem.selectedTabKey === 'filterData'">
          <a-table ref="filterTable" rowKey="rowKey" :columns="dataItem.tableColumns" :dataSource="dataItem.filterData" :pagination="false"></a-table>
        </div>
        <div class="" v-if="dataItem.selectedTabKey === 'totalData'">
          <a-table rowKey="rowKey" :columns="dataItem.tableColumns" :dataSource="dataItem.sourceData" :pagination="false"></a-table>
        </div>
      </a-card>
    </div>
  </div>
</template>

<script>

import XLSX from 'xlsx'
import moment from 'moment'

export default {
  name: 'Winnie',
  data () {
    return {
      option: {
        totalColumnsOfFile: 99,
        advanceActiveKey: null
      },
      configuration: {
        // 时间过滤参数
        rangeTime: [],
        columnOfTime: 3,
        formatOfRangeTime: 'YYYY/MM/DD hh:mm:ss',

        // 总分过滤参数
        columnOfTotalScore: 8,
        filterValueOfTotalScore: 90,

        // sheet指定
        sheetIndex: 1,

        // 重复数据过滤列数
        replicateFilterIndex: 10,

        // 提取数据的列数集合
        columnsOfData: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
      },
      fileList: [],

      // 统计数据
      sourceData: [],
      statisticsData: [],

      analyseData: []
    }
  },
  created () {
    if (localStorage.getItem('winnie-data-analyse')) {
      this.configuration = JSON.parse(localStorage.getItem('winnie-data-analyse')) || {}
    }
    this.configuration.rangeTime = [moment().startOf('isoWeek'), moment().endOf('isoWeek')]
  },
  methods: {
    saveConfigurationData () {
      localStorage.setItem('winnie-data-analyse', JSON.stringify(this.configuration))
    },
    toggleAdvanceSetting () {
      this.option.advanceActiveKey = this.option.advanceActiveKey ? null : ['advanceSetting']
    },
    getTabList (dataItem) {
      return [{
        key: 'dashboard',
        tab: '概述'
      }, {
        key: 'filterData',
        tab: '及格的数据(' + dataItem.filterDataTotalCount + '条)'
      }, {
        key: 'totalData',
        tab: '所有数据(' + dataItem.sourceDataTotalCount + '条)'
      }]
    },
    handleRemove (file) {
      const index = this.fileList.indexOf(file)
      const newFileList = this.fileList.slice()
      newFileList.splice(index, 1)
      this.fileList = newFileList
    },
    beforeUpload (file) {
      this.fileList = [...this.fileList, file]
      return false
    },
    statisticsDataAction () {
      // 清除analyseData的数据
      this.analyseData = []

      // 收集数据
      if (this.fileList == null || this.fileList.length <= 0) {
        this.$message.error('请添加需要分析的文件')
        return
      }
      for (let indexOfFile = 0; indexOfFile < this.fileList.length; indexOfFile++) {
        const fileItem = this.fileList[indexOfFile]

        const fileReader = new FileReader()
        fileReader.onload = (e) => {
          const data = new Uint8Array(e.target.result)
          const workbook = XLSX.read(data, { type: 'array' })
          const firstWorksheet = workbook.Sheets[workbook.SheetNames[this.configuration.sheetIndex - 1]]
          const dataJson = XLSX.utils.sheet_to_json(firstWorksheet, { header: 1 })

          // 将第一行的标题栏集合移除
          const titlesData = dataJson.splice(0, 1)

          const dataSource = this.convertSourceData(dataJson)
          const filterData = this.filterData(dataSource)
          const filterTitles = this.filterTitles(titlesData)

          this.analyseData.push({
            fileName: fileItem.name,
            selectedTabKey: 'dashboard',
            sourceTitles: titlesData,
            filterTitles: filterTitles,
            tableColumns: this.getTableColumns(filterTitles[0]),
            sourceData: dataSource,
            sourceDataTotalCount: dataSource.length,
            filterData: filterData,
            filterDataTotalCount: filterData.length
          })
        }
        fileReader.readAsArrayBuffer(fileItem)
      }
    },
    convertSourceData (sourceData) {
      // 将sourceData从二维数组转化为对象数组
      const convertedSourceData = []

      sourceData.forEach((dataArray, arrayIndex) => {
        const sourceDataItem = {}
        dataArray.forEach((dataItem, itemIndex) => {
          sourceDataItem[itemIndex] = dataItem
        })
        convertedSourceData.push(sourceDataItem)
      })

      return convertedSourceData
    },
    filterTitles (titles) {
      const filterTitles = []
      for (let index = 0; index < titles.length; index++) {
        const dataItem = titles[index]
        const tempData = {}
        for (const key in dataItem) {
          if (this.configuration.columnsOfData.includes(parseInt(key))) {
            tempData[key - 1] = dataItem[key - 1]
          }
        }
        filterTitles[index] = tempData
      }
      return filterTitles
    },
    filterData (datas) {
      let filterData = datas

      // 根据时间过滤数据
      filterData = this.filterByRangeTime(filterData)

      //
      filterData = this.filterByTotalScore(filterData)

      //
      filterData = this.filterByColumns(filterData)

      //
      filterData = this.filterByReplicate(filterData)

      return filterData
    },
    filterByReplicate (datas) {
      if (!this.configuration.replicateFilterIndex) {
        return datas
      }
      const filterData = []
      const replicateData = {}
      datas.forEach((item) => {
        // 如果replicateData按照key已经存在了
        if (replicateData[item[this.configuration.replicateFilterIndex - 1]]) {
          // 分值比较
          let oldValue = replicateData[item[this.configuration.replicateFilterIndex - 1]][this.configuration.columnOfTotalScore - 1]
          oldValue = parseFloat(oldValue)

          let newValue = item[this.configuration.columnOfTotalScore - 1]
          newValue = parseFloat(newValue)

          // 数据的替换
          if (newValue > oldValue) {
            filterData.splice(replicateData[item[this.configuration.replicateFilterIndex - 1]].indexOfFilterData, 1, item)
            replicateData[item[this.configuration.replicateFilterIndex - 1]] = item
          }
        } else {
          replicateData[item[this.configuration.replicateFilterIndex - 1]] = item
          filterData.push(item)
          replicateData[item[this.configuration.replicateFilterIndex - 1]].indexOfFilterData = filterData.length - 1
        }
      })
      return filterData
    },
    filterByColumns (datas) {
      if (!this.configuration.columnsOfData || this.configuration.columnsOfData.length <= 0) {
        return datas
      }

      const filterData = []
      // 过滤掉不在columnsOfData内的列数的属性
      for (let index = 0; index < datas.length; index++) {
        const dataItem = datas[index]
        const tempData = {}
        for (const key in dataItem) {
          if (this.configuration.columnsOfData.includes(parseInt(key))) {
            tempData[key - 1] = dataItem[key - 1]
          }
        }
        tempData.rowKey = index
        filterData[index] = tempData
      }
      return filterData
    },
    filterByTotalScore (datas) {
      // 总分的过滤
      if (!this.configuration.columnOfTotalScore || !this.configuration.filterValueOfTotalScore) {
        return datas
      }
      return datas.filter((dataItem) => {
        return parseFloat(dataItem[this.configuration.columnOfTotalScore - 1]) >= parseFloat(this.configuration.filterValueOfTotalScore)
      })
    },
    filterByRangeTime (datas) {
      /*
        时间过滤
        rangeTime: [],
        columnOfTime: 2,
        formatOfRangeTime: 'YYYY/MM/DD hh:mm:ss',
       */
      if (!this.configuration.columnOfTime || !this.configuration.formatOfRangeTime) {
        return datas
      }

      if (!this.configuration.rangeTime || this.configuration.rangeTime.length <= 0) {
        return datas
      }

      const startDate = this.configuration.rangeTime.length > 0 ? this.configuration.rangeTime[0] : null
      const endDate = this.configuration.rangeTime.length > 1 ? this.configuration.rangeTime[1] : null

      return datas.filter((dataItem, index) => {
        dataItem.rowKey = index
        const dateItemTime = moment(dataItem[this.configuration.columnOfTime - 1], this.configuration.formatOfRangeTime)

        let result = false

        if (startDate) {
          result = dateItemTime.isAfter(startDate)
        }
        if (endDate) {
          result = dateItemTime.isBefore(endDate)
        }

        return result
      })
    },
    getTableColumns (titleObject) {
      const tableColumns = []

      for (const key in titleObject) {
        tableColumns.push({
          title: titleObject[key],
          dataIndex: key
        })
      }

      return tableColumns
    },
    exportFilterData (dataItem) {
      const sheetJsonData = this.convertFilterDataToSheetJsonData(dataItem)
      const sheetData = XLSX.utils.json_to_sheet(sheetJsonData)
      this.openDownloadDialog(this.sheet2blob(sheetData), dataItem.fileName + '_及格数据.xlsx')
    },
    convertFilterDataToSheetJsonData (dataItem) {
      const sheetJsonData = []

      dataItem.filterData.forEach((item) => {
        const tempItem = {}
        for (const key in item) {
          if (dataItem.filterTitles[0][key]) {
            tempItem[dataItem.filterTitles[0][key]] = item[key]
          }
        }
        sheetJsonData.push(tempItem)
      })

      return sheetJsonData
    },
    // 将一个sheet转成最终的excel文件的blob对象，然后利用URL.createObjectURL下载
    sheet2blob (sheet, sheetName) {
      sheetName = sheetName || 'sheet1'
      const workbook = {
        SheetNames: [sheetName],
        Sheets: {}
      }
      workbook.Sheets[sheetName] = sheet // 生成excel的配置项

      const wopts = {
        bookType: 'xlsx', // 要生成的文件类型
        bookSST: false, // 是否生成Shared String Table，官方解释是，如果开启生成速度会下降，但在低版本IOS设备上有更好的兼容性
        type: 'binary'
      }
      const wbout = XLSX.write(workbook, wopts)
      const blob = new Blob([s2ab(wbout)], {
        type: 'application/octet-stream'
      }) // 字符串转ArrayBuffer
      function s2ab (s) {
        const buf = new ArrayBuffer(s.length)
        const view = new Uint8Array(buf)
        for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
        return buf
      }

      return blob
    },
    openDownloadDialog (url, saveName) {
      if (typeof url === 'object' && url instanceof Blob) {
        url = URL.createObjectURL(url) // 创建blob地址
      }
      const aLink = document.createElement('a')
      aLink.href = url
      aLink.download = saveName || '' // HTML5新增的属性，指定保存文件名，可以不要后缀，注意，file:///模式下不会生效
      let event
      if (window.MouseEvent) {
        event = new MouseEvent('click')
      } else {
        event = document.createEvent('MouseEvents')
        event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
      }
      aLink.dispatchEvent(event)
    }
  }
}
</script>

<style lang="less" scoped>
  @import "winnie.less";
</style>
